package LDraw.Support;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* LDrawFastSet.h
* Bricksmith
*
* Created by bsupnik on 9/15/12.
* Copyright 2012 __MyCompanyName__. All rights reserved.
*
*/
/**
* @Class LDrawFastSet
*
* @Represent LDrawFastSet.h of Bricksmith
*
* @author funface2
* @since 2014-03-13
*
*/
// LDrawFastSet - THEORY OF OPERATION
//
// Here's the problem: the overhead of NS collections is relatively high, and
// attaching a
// mutable set to each directive to keep track of who is observing it basically
// doubles
// the number of NS containers and load time.
//
// Buuuuut - in nearly every important case, the nubmer of objects in a
// container is 1.
// So the fast set structure optimizes away the NS mutable set for the simple
// cases where
// we don't need a real set.
//
// ENCODING
//
// The fast set is a pair of pointers with the following encoding rules:
//
// p1 p2 meaning
// NULL NULL The set is empty.
// id1 NULL The set contains one object, refered to via id1.
// id1 id2 The set contains two objects, referred to via id1 and id2.
// NULL id2 The set contains at least 3 objects, contained in an NSMutableSet
// stored in id2.
public class LDrawFastSet<T> {
// 2�� �����϶� p1, p2�� ����. �� �̻��϶� Set�� ����. ����? ��κ��� ���� 2�� ���϶� �ӵ� �ø��� ����.
/**
* @uml.property name="isContainsMoreThan2Items"
*/
boolean isContainsMoreThan2Items = false;
/**
* @uml.property name="p1"
*/
T p1;
/**
* @uml.property name="p2"
*/
T p2;
/**
* @uml.property name="tree_set"
*/
TreeSet<T> tree_set;
private Lock mutex;
public LDrawFastSet() {
p1 = p2 = null;
mutex = new ReentrantLock(true);
}
public boolean isContains(T item) {
if (isContainsMoreThan2Items == false) {
if (p1 == item)
return true;
if (p2 == item)
return true;
return false;
} else
return tree_set.contains(item);
}
public void remove(T item) {
if (isContainsMoreThan2Items == true) {
mutex.lock();
tree_set.remove(item);
mutex.unlock();
if (tree_set.size() == 0)
isContainsMoreThan2Items = false;
} else {
if (p1 == item) {
p1 = p2;
p2 = null;
} else if (p2 == item) {
p2 = null;
}
}
}
public void add(T item) {
assert item!=null;
if (isContains(item) == true)
return;
if (p1 == null)
p1 = item;
else if (p2 == null)
p2 = item;
else {
isContainsMoreThan2Items = true;
if (tree_set == null)
tree_set = new TreeSet<T>();
mutex.lock();
tree_set.add(item);
mutex.unlock();
}
}
public void removeAll(){
isContainsMoreThan2Items=false;
mutex.lock();
tree_set.clear();
mutex.unlock();
p1=p2=null;
}
public Set<T> getAllItems(){
TreeSet<T> treeSet = new TreeSet<T>();
if(p1!=null)
treeSet.add(p1);
if(p2!=null)
treeSet.add(p2);
if(isContainsMoreThan2Items==true){
mutex.lock();
treeSet.addAll(tree_set);
mutex.unlock();
}
return treeSet;
}
}